
import socket
import json
import sqlite3
import time
import threading
import random

import backend.DID.DID_interface as did_interface
import backend.P2P.auth as  auth
import backend.P2P.interface_management as interface_management
import backend.DID.Certification_Management as Certification_Management

#本机到跨机同步，与跨机到本机同步
#在按登录按钮之前，身份认证完成瞬间
# 跨机向本机发请求，请求数据为好友信息，群聊信息，用户本机设备信息，聊天记录并监听前端发来的数据
def send_sync_request_to_host(my_did,modules):#my_did即跨机上正在登录的用户did=本机底层did
    try:
     #sender_did是跨机底层绑定的用户的DID(my_did)
     #receiver_did是跨机底层绑定的用户的did
            stop_event = threading.Event()   #结束信号
            Certification_Management.broadcast_find_host(my_did,stop_event)#广播寻找一次本机
            host_ip =  Certification_Management.listen_for_host_response()#监听本机回复，获取本机ip
            with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
                    cursor = conn.cursor()
                    cursor.execute('''select id from user where host = 1''')#在跨机上寻找跨机底层did
                    res = cursor.fetchone()
                    kuaji_did = res[0]
                    # 构造同步请求（模块明确指出需要哪些内容）
                    request = {
                        "action": "SYNC_REQUEST",
                        "sender": my_did,
                        "kuaji_did":kuaji_did,
                        "modules": modules # 指定需要同步basic_info(包括好友信息和群聊信息),messages
                    }
                    

                    # 跨机发送请求并且监听回复，接收数据
                    data = did_interface.meg_sync_require(kuaji_did,my_did,host_ip,request)#data是明文json，=decrypt_data
                    
                    #在跨机上存这个数据
                    basic_info = data.get("basic_info")
                    friend = basic_info.get("friends")
                    group = basic_info.get("groups")
                    messages = data.get("messages")

                    if modules == basic_info:
                        if basic_info["friends"]:
                            save_friends(friend)
                        if basic_info["groups"]:
                            save_groups(group)
                    else:
                        save_messages(messages)     
                    

                    #跨机定期检测与本机的信息的差异，把跨机上多的部分传给本机   
                    #跨机先查询各信息中最大的timestamp
                    # 初始最大时间戳记录
                    local_ts_dict = {
                        "friend": get_local_max_ts("friends"),
                        "group": get_local_max_ts("tblGroup"),
                        "friend_messages": get_local_max_ts("messages"),
                        "group_messages": get_local_max_ts("group_message")
                    }           
            # 启动定期同步线程
            threading.Thread(target=periodic_diff_push_to_host, args=(kuaji_did,my_did, host_ip, local_ts_dict), daemon=True).start()
            return True           
    except Exception as e:
        print(f"[同步异常]: {e}")
        return False
    
#查本机各表最大的timestamp
def get_local_max_ts(tablename):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute('''select id from current_user''')
            row = cursor.fetchone()
            owner_did = row[0]

            cursor.execute(f"SELECT timestamp FROM {tablename} WHERE owner = ?", (owner_did,))
            res = cursor.fetchone()
            return res

#定期发送差异数据
def periodic_diff_push_to_host(kuaji_did,my_did, host_ip, last_ts_dict):
    while True:
        time.sleep(30)

        # 最新时间戳
        new_ts_dict = {
            "friend": get_local_max_ts("friends"),
            "group": get_local_max_ts("tblGroup"),
            "friend_messages": get_local_max_ts("messages"),
            "group_messages": get_local_max_ts("group_message")
        }

        diff_data = {}

        # 查找朋友表新增数据
        if new_ts_dict["friend"] > last_ts_dict["friend"]:
            diff_data["friends"] = get_data_after_ts("friends", last_ts_dict["friend"])
            last_ts_dict["friend"] = new_ts_dict["friend"]

        if new_ts_dict["group"] > last_ts_dict["group"]:
            diff_data["groups"] = get_data_after_ts("tblGroup", last_ts_dict["group"])
            last_ts_dict["group"] = new_ts_dict["group"]

        if new_ts_dict["friend_messages"] > last_ts_dict["friend_messages"]:
            diff_data["friend_messages"] = get_data_after_ts("messages", last_ts_dict["friend_messages"])
            last_ts_dict["friend_messages"] = new_ts_dict["friend_messages"]

        if new_ts_dict["group_messages"] > last_ts_dict["group_messages"]:
            diff_data["group_messages"] = get_data_after_ts("group_message", last_ts_dict["group_messages"])
            last_ts_dict["group_messages"] = new_ts_dict["group_messages"]

        if diff_data:
            # 构造同步差异包
            package = {
                "action": "SYNC_DIFF",
                "sender": my_did,
                "data": diff_data
            }
            # 发送给本机
            did_interface.meg_sync_send(kuaji_did,my_did,package,host_ip)

#从指定数据库表中查询“时间戳大于 ts 的新数据”，用于找出差异数据
def  get_data_after_ts(table,ts):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute('''select id from current_user''')
            row = cursor.fetchone()
            owner_did = row[0]
            cursor.execute(f"SELECT * FROM {table} WHERE timestamp > ? and owner = ?", (ts,owner_did,))
            rows = cursor.fetchall()

    # 建议你将rows转换为字典list
    return [dict_from_row(row, table) for row in rows]

#将数据库中查到的一条数据（row）转成一个 Python 字典，方便后续传输或转换成 JSON
def dict_from_row(row, table_name):
    """
    将数据库查询结果 row 转为字典，根据不同表结构处理。
    """
    # 获取设备信息
    cpu_id, disk_id, product_id = auth.get_device_info()

    if table_name == "friends":
        # 假设 friends 表结构为 (id, name, ip,online,host_id, timestamp)
        return {
            "id": row[0],
            "name": row[1],
            "ip": row[2],
            "online":row[3],
            "host_id":row[4],
            "timestamp": row[5]
        }

    elif table_name == "tblGroup":
        # 假设 tblGroup 表结构为 (groupId, groupname, members, timestamp,owner)
        return {
            
            "groupId": row[0],
            "groupname": row[1],
            "members": row[2],  # 可能是 JSON 字符串
            "timestamp": row[3],
            "owner":row[4]
        }

    elif table_name == "messages":
         
        message = did_interface.decrypt(cpu_id, disk_id, product_id, row["message"])
        # 假设 messages 表结构为  (id, friend_id, sent, message, timestamp,is_sent,owner)
        return {
            "id": row[0],
            "friend_id": row[1],
            "sent": row[2],
            "message": message,
            "timestamp": row[4],
            "is_sent":row[5],
            "owner":row[6]
        }

    elif table_name == "group_message":
        # 假设 group_message 表结构为(sender,receiver,message,timestamp,msg_type,groupId,owner)
        group_message = did_interface.decrypt(cpu_id, disk_id, product_id, row["message"])
        return {
            "sender": row[0],
            "receiver": row[1],
            "message": row[2],
            "message": group_message,
            "timestamp": row[4],
            "msg_type":row[5],
            "groupId":row[6],
            "owner":row[7]
        }

    else:
        raise ValueError(f"Unsupported table: {table_name}")

#!!!!!!!!!!!
#本机监听跨机的请求，并把数据获取，发送给跨机,
# 本机定期接受跨机发来的同步数据
def start_sync_server():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('', 9900))  # 本机监听 TCP 端口
    s.listen(5)
    print("[本机] 正在监听同步请求 on TCP 9900...")

    while True:
        conn, addr = s.accept()
        print(f"[本机] 接收到来自 {addr} 的同步请求")

        try:
            data = conn.recv(4096)
            request = json.loads(data.decode())
            owner = request.get("sender")  # 用 sender(跨机发请求的用户就是当前用户) 来当 owner

            if request.get("action") == "SYNC_REQUEST":
                modules = request.get("modules", [])  # 可能有 "friends"、"groups","User","messages"
                response = {}
                # 最终response={
                # "basic_info": {
                #     "friends": [...],
                #     "groups": [...]
                # },
                # "messages": [...]
                # }

                # 基础信息打包在 basic_info 下
                basic_info = {}

                if "friends" in modules:
                    basic_info["friends"] = get_all_friends(owner)  # 从数据库获取好友信息

                if "groups" in modules:
                    basic_info["groups"] = get_all_groups(owner)  # 从数据库获取群聊信息

                # if "user_info" in modules:
                #     basic_info["user_info"] = get_User_info(owner)  # 从数据库获取用户本机的设备信息

                if basic_info:
                    response["basic_info"] = basic_info  # 将 key 为 "basic_info" 的一整块数据加入 response 中

                # 聊天记录
                if "messages" in modules:
                    response["messages"] = get_all_messages(owner)  # 从数据库获取聊天记录

                # 发送统一打包响应
                conn.send(json.dumps(response).encode())
                print("[本机] 同步数据已发送")

        except Exception as e:
            print(f"[本机] 处理同步请求时出错: {e}")

        # finally:
            # conn.close()

# 本机从数据库读好友基础信息，加载好友信息时也可调用
def get_all_friends(owner):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT id, name, ip, online,owner FROM friends where owner=?",(owner,))
            rows = cursor.fetchall()#取出所有的好友信息
            print(rows)
    # 构建成列表字典格式
    friends = []
    for row in rows:
        friend = {
            "id": row[0],
            "name": row[1],
            "ip": row[2],
            "online": bool(row[3]),  # 转换成 True/False
            "owner": row[4],
            # "icon": interface_management.path_to_base64("backend/image.png")
        }
        friends.append(friend)
       
    # conn.close()
    return friends
     
# 本机从数据库读群聊基础信息，加载群聊信息时也可调用
def get_all_groups(owner):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
        cursor = conn.cursor()   
        cursor.execute("SELECT groupId, groupname, members, timestamp, owner FROM tblGroup WHERE owner = ?", (owner,))
        rows = cursor.fetchall()

        groups = []
        for row in rows:
            try:
                members = json.loads(row[2]) if row[2] else []
            except Exception as e:
                print(f"[解析群成员JSON失败]: {e}")
                members = []
            group = {
                # "icon": interface_management.path_to_base64("backend/P2P/小黑.png"),
                "groupId": row[0],
                "groupname": row[1],
                "members": members,  # 这里是列表/字典
                "timestamp": row[3],
                "owner": row[4]
            }
            groups.append(group)

        return groups

# 本机从数据库获取用户信息(主要是获取本机设备信息info)
def get_User_info(owner):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT info from User where name = ?", (owner,))
            user_info = cursor.fetchone()
            # conn.close()
            return user_info

# 本机从数据库读取单人和群聊聊天记录
def get_all_messages(owner):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            #获取设备信息
            cpu_id, disk_id, product_id = auth.get_device_info()

            # 获取单聊记录
            cursor.execute("SELECT id, friend_id, sent,message, timestamp ,is_sent ,owner FROM messages where owner = ?",(owner,))
            private_rows = cursor.fetchall()
            private_msgs = []
            for row in private_rows:
                message = did_interface.decrypt(cpu_id, disk_id, product_id, row["message"])#解密这条消息
                private_msgs.append({
                    "id": row[0],
                    "friend_id": row[1],
                    "sent": row[2],
                    "message":message,
                    "timestamp":row[4],
                    "is_sent":row[5],
                    "owner":owner
                })
                
            # 获取群聊记录
            cursor.execute("SELECT sender,receiver, message, timestamp,msg_type, groupId,owner FROM group_message where owner = ?",(owner,))
            group_rows = cursor.fetchall()
            group_msgs = []
            for group_row in group_rows:
                group_message = did_interface.decrypt(cpu_id, disk_id, product_id, group_row["message"])#解密这条消息
                group_msgs.append({
                    "sender": group_row[0],
                    "receiver": group_row[1],
                    "message": group_message,
                    "timestamp": group_row[3],
                    "msg_type":group_row[4],
                    "groupId":group_row[5],
                    "owner":owner
                })

    conn.close()
    #打包成统一结构
    messages={
        "private": private_msgs,
        "group": group_msgs
    }
  
    return  messages

# 跨机存本机传来好友信息
def save_friends(friend):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute('''
                INSERT OR REPLACE INTO messages(id, name, ip, online,owner)
                VALUES (?, ?, ?, ?, ?)
            ''', (friend["id"], friend["name"], friend["ip"], int(friend["online"]), friend["owner"]))

# 跨机存本机传来的群聊信息
def save_groups(group):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute('''
                    INSERT OR REPLACE INTO group_message (id, groupname, ip,  online,owner)
                    VALUES (?, ?, ?, ?, ?)
                ''', (
            group["groupId"], group["groupname"], group["members"], group["timestamp"], group["owner"]))

        # 跨机存本机传来的用户信息里面的设备info
def save_User_info(user_info):
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            cursor.execute('''
                    INSERT OR REPLACE INTO User (info)
                    VALUES (?, ?, ?, ?, ?,?)
                ''', (user_info["info"]))

# 跨机存本机传来聊天记录
def save_messages(message_data):#message_data是获得解密后的明文
    #获取设备信息
    cpu_id, disk_id, product_id = auth.get_device_info()

    #对这条消息加密存储
    message_content = did_interface.decrypt(cpu_id, disk_id, product_id, message_data["message"])#解密这条消息内容
    with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            cursor = conn.cursor()
            # 判断是群聊 or 私聊
            if "groupId" in message_data:
                # 群聊消息
                cursor.execute('''
                    INSERT INTO group_message ( sender,receiver, message, timestamp,msg_type, groupId,owner)
                    VALUES (?, ?, ?, ?,?)
                ''', (message_data["sender"], message_data["receiver"], message_content, message_data["msg_type"],
                    message_data["groupId"], message_data["owner"]))
            else:
                # 单聊消息
                cursor.execute('''
                    INSERT INTO messages (id, friend_id, sent,message, timestamp ,is_sent,owner)
                    VALUES (?, ?, ?, ?)
                ''', (message_data["id"], message_data["friend_id"], message_data["sent"], message_content,
                    message_data["timestamp"], message_data["is_sent"], message_data["owner"]))
                



